﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;

namespace BGShell.PowerShell
{
    internal static class PSLanguage
    {
        public static string FormatNumber(Int32 value)
        {
            return value.ToString(CultureInfo.CurrentCulture);
        }

        public static string FormatTypeName(Type type)
        {
            return FormatTypeName(type, false);
        }

        public static string FormatTypeName(Type type, Boolean withoutNamespace)
        {
            if (type.HasElementType)
            {
                var elementName = FormatTypeName(type.GetElementType(), withoutNamespace);

                if (type.IsArray)
                {
                    return elementName + '[' + new string(',', type.GetArrayRank() - 1) + ']';
                }
                else if (type.IsByRef)
                {
                    return elementName + '&';
                }
                else if (type.IsPointer)
                {
                    return elementName + '*';
                }
            }

            if (BuiltinTypes.ContainsKey(type.FullName))
            {
                return BuiltinTypes[type.FullName];
            }

            var typeName = type.Name;
            var result = new StringBuilder();

            if (!type.IsNested && !withoutNamespace)
            {
                const string SysNS = "System";

                var ns = type.Namespace;

                if (!string.IsNullOrEmpty(ns) && !SysNS.Equals(ns, StringComparison.Ordinal))
                {
                    if (ns.Substring(0, SysNS.Length).Equals(SysNS, StringComparison.Ordinal))
                    {
                        result.Append(ns, SysNS.Length + 1, ns.Length - SysNS.Length - 1);
                        result.Append('.');
                    }
                }
            }


            if (type.IsGenericType)
            {
                typeName = typeName.Replace("`", "``");
            }

            if (type.IsNested)
            {
                typeName = FormatTypeName(type.DeclaringType, withoutNamespace) + '+' + typeName;
            }

            result.Append(typeName);

            if (type.IsGenericType && !type.IsGenericTypeDefinition)
            {
                result.Append('[');

                foreach (var arg in type.GetGenericArguments())
                {
                    result.Append(arg.FullName);
                    result.Append(", ");
                }

                result.Length -= 2;
                result.Append(']');
            }

            return result.ToString();
        }

        public static Dictionary<String, String> GetBuiltinTypes()
        {
            var dict = new Dictionary<String, String>(StringComparer.Ordinal);

            dict["System.Boolean"] = "Bool";
            dict["System.Int32"] = "Int";
            dict["System.Int64"] = "Long";
            dict["System.Single"] = "Float";

            dict["System.Collections.Hashtable"] = "Hashtable";

            dict["System.DirectoryServices.DirectoryEntry"] = "Adsi";
            dict["System.DirectoryServices.DirectorySearcher"] = "AdsiSearcher";

            dict["System.Management.ManagementClass"] = "WmiClass";
            dict["System.Management.ManagementObject"] = "Wmi";
            dict["System.Management.ManagementObjectSearcher"] = "WmiSearcher";

            dict["System.Management.Automation.PSObject"] = "PSObject";
            dict["System.Management.Automation.PSReference"] = "Ref";
            dict["System.Management.Automation.ScriptBlock"] = "ScriptBlock";
            dict["System.Management.Automation.SwitchParameter"] = "Switch";

            dict["System.Net.IPAddress"] = "IPAddress";

            dict["System.Text.RegularExpressions.Regex"] = "Regex";

            dict["System.Xml.XmlDocument"] = "Xml";

            return dict;
        }

        private static readonly Dictionary<String, String> BuiltinTypes = GetBuiltinTypes();
    }
}
